#ifndef _MATHEMATICS_COMPARISON_H_
#define _MATHEMATICS_COMPARISON_H_

#include "./math_define.h"

namespace Mathematics {
	//! Consecutive comparison
	/*!
		class for making quick consecutive comparisons inside an if test using
		relational operators.
		Please use only one type per comparison, or else...
	*/
	class Comparison {
	protected:
		/*! State of the comparison object. Tells if all the comprarisons were true or not. */
		bool result;
		
		//! auxiliar function for changing the last registered value into the new one, but returning the old one
		template< class T >
			T storeExchange( const T &value ){
				/*! Holds the last value used. */
				static T perm;
#ifdef DEBUG
				cout << "Change: " << perm << " to " << value << pendl;
#endif
				T temp = perm;
				perm = value;
				return temp;
			};
		
	public:
		//! default constructor
		Comparison():result(true) {};
		//! copy constructor
		Comparison( const Comparison &original ):result(original.result) {};
		//! default destructor
		~Comparison() {};
		
		/*!
			Begins a comparison.
			\param value the first value to compare (leftmost)
			\return The comparison object, ready to go.
			
			\code
			Comparison cmp;
			if( cmp << 1.0 < 2.0 > 0.5 == 0.5 != 1.25 >= 1.25 <= 2.22 )
				// true!
			\endcode
		*/
		template< class T >
			inline Comparison& operator << ( const T &value ){
				storeExchange(value);
				result = true;
				return (*this);
			};
		
		/*!
			Makes a comparison.
			\param value the next value to compare.
			\return The comparison object, ready to keep comparing.
			
			\code
			Comparison cmp;
			if( cmp << 1.0 < 2.0 < 3.0 < 4.0 ){
				// true! get in here.
			}
			if( cmp << 1.0 < 3.0 < 3.0 < 4.0 ){
				// false! don't get in here.
			}
			\endcode
		*/
		template< class T >
			inline Comparison& operator < ( const T &value ){
				result &= storeExchange( value ) < value;
				return (*this);
			};
		/*!
			Makes a comparison.
			\param value the next value to compare.
			\return The comparison object, ready to keep comparing.
			
			\code
			Comparison cmp;
			if( cmp << 1.0 <= 2.0 <= 3.0 <= 4.0 ){
				// true! get in here.
			}
			if( cmp << 1.0 <= 3.0 <= 2.9 <= 4.0 ){
				// false! don't get in here.
			}
			\endcode
		*/
		template< class T >
			inline Comparison& operator <= ( const T &value ){
				result &= storeExchange( value ) <= value;
				return (*this);
			};
		/*!
			Makes a comparison.
			\param value the next value to compare.
			\return The comparison object, ready to keep comparing.
			
			\code
			Comparison cmp;
			if( cmp << 1.0 > 2.0 > 3.0 ){
				// false! don't get in here.
			}
			if( cmp << 4.0 > 3.0 > 1.0 ){
				// true! get in here.
			}
			\endcode
		*/
		template< class T >
			inline Comparison& operator > ( const T &value ){
				result &= storeExchange( value ) > value;
				return (*this);
			};
		/*!
			Makes a comparison.
			\param value the next value to compare.
			\return The comparison object, ready to keep comparing.
			
			\code
			Comparison cmp;
			if( cmp << 1.0 >= 2.0 >= 3.0 ){
				// false! don't get in here.
			}
			if( cmp << 4.0 >= 3.0 >= 1.0 ){
				// true! get in here.
			}
			\endcode
		*/
		template< class T >
			inline Comparison& operator >= ( const T &value ){
				result &= storeExchange( value ) >= value;
				return (*this);
			};
		/*!
			Makes a comparison.
			\param value the next value to compare.
			\return The comparison object, ready to keep comparing.
			
			\code
			Comparison cmp;
			if( cmp << 1.0 < 2.0 == 2.0 < 4.0 ){
				// true! get in here.
			}
			if( cmp << 1.0 < 3.0 == 3.0 == 4.0 ){
				// false! don't get in here.
			}
			\endcode
		*/
		template< class T >
			inline Comparison& operator == ( const T &value ){
				result &= storeExchange( value ) == value;
				return (*this);
			};
		/*!
			Makes a comparison.
			\param value the next value to compare.
			\return The comparison object, ready to keep comparing.
			
			\code
			Comparison cmp;
			if( cmp << 1.0 != 2.0 < 3.0 != 4.0 ){
				// true! get in here.
			}
			if( cmp << 1.0 != 3.0 != 3.0 < 4.0 ){
				// false! don't get in here.
			}
			\endcode
		*/
		template< class T >
			inline Comparison& operator != ( const T &value ){
				result &= storeExchange( value ) != value;
				return (*this);
			};
		
		/*!
			Operator for conversion to bool type.
			Often used in an if test.
			\return The bool state of the comparison object.
			
			\code
			Comparison cmp;
			if( cmp << 1.0 != 2.0 < 3.0 != 4.0 ){
				// true! get in here.
			}
			\endcode
		*/
		inline operator bool (){
			return result;
		};
		
	};
	
	/*!
		Default comparison object.
		Don't care about creating one new. This one can handle.
	*/
	extern Comparison cmp;
	
};

#endif //_MATHEMATICS_COMPARISON_H_
